package cn.shaines.filesystem.util;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Scanner;
public class CalculatePi2 {
    static final int PRECISION_VALUE = 20000  ; // 计算的 精度值，pi 保留多少位小数
    public static void main(String[] args) {
        Scanner scan=new Scanner(System.in);
        System.out.println("\n请输入计算次数多少次 ：");  // 50
        int z=scan.nextInt();
        calculate_improve2_byBigDecimal(z) ;
    }
    static volatile LinkedHashMap<Integer,LinkedHashMap<Integer,Integer> > li2 = new LinkedHashMap<>() ;
    static final BigDecimal B0 = new BigDecimal("0").setScale(PRECISION_VALUE,RoundingMode.HALF_UP)   ;
    static final BigDecimal B1 = new BigDecimal("1").setScale(PRECISION_VALUE,RoundingMode.HALF_UP)   ;
    static final BigDecimal B2 = new BigDecimal("2").setScale(PRECISION_VALUE,RoundingMode.HALF_UP)   ;
    static volatile BigDecimal sum = new BigDecimal("0").setScale(PRECISION_VALUE,RoundingMode.HALF_UP)   ;
    static volatile BigDecimal ji =  new BigDecimal("1").setScale(PRECISION_VALUE,RoundingMode.HALF_UP)   ;
    private static double calculate_improve2_byBigDecimal( int cnt ) {
//        建议用法，使用字符串格式构造，不会损失精度:  BigDecimal num = new BigDecimal("2.222222");
        final int y_begin = 3 ;
        sum = B0 ;
        class Thread1 extends  Thread{
            boolean ifFinished = false ;
            //收集分母的数组数据
            @Override
            public void run() {
                super.run();
                for( int i = 1 ; i <= cnt   ; i ++  ){
                    if( li2.get(i) == null ){
                        li2.put( i , new LinkedHashMap< >() )  ;
                    }
                    for( int j = 1 ; j <= i  ; j++){
                        if( j == 1 ){
                            li2.get(i).put( j , y_begin ) ;
                        }else{
                            li2.get(i).put(  j , li2.get(i).get(j-1) + 2   ) ;
                        }
                    }
                    //计算并汇总结果，然后显示
                    //计算，然后从 map中 移除输入的变量，节省内存
                    ji = B1 ;
                    Integer key = i ;
                    LinkedHashMap<Integer,Integer>  inner_map =  li2.get(i)  ;
                    if( inner_map!=null && inner_map.size() > 0 ){
                        // 比较数量，看是否可以开始运算了。不能在数据尚未准备完毕的时候就开始计算
                        assert( key!=null && key == inner_map.size()) ;
                        for( Map.Entry<Integer,Integer> entry2 : inner_map.entrySet()  ) {
                            try{
                                ji  = ji .multiply (
                                        new BigDecimal(entry2.getKey()+"").setScale(PRECISION_VALUE,RoundingMode.HALF_UP)
                                                .divide (
                                                        new BigDecimal(entry2.getValue()+"")  , 10 , RoundingMode.HALF_UP    // 关键，不然会报错 ： java.lang.ArithmeticException  Non-terminating decimal expansion; no exact representable decimal result
                                                )
                                );
                            }catch (Exception e){
                                e.printStackTrace();
                            }
                        }
                        sum  = sum.add(ji) ;
                        if(i<cnt){
                            li2.remove(i) ; //移除，释放内存
                        }
                    }
                    if( i% 100 == 0 ){
                        ptl("当前运算到"+i+"次了，当前π约等于："+  (sum.add(B1) ).multiply(B2) );
                    }
                }
                ptl("\n分母\n" + li2.toString() );
                ifFinished = true ;
                ptl( "Thread1 运行结束");
                ptl("\n请输入计算次数多少次 ，为"+cnt+"的条件下，π约等于：\n"+  (sum.add(B1) ).multiply(B2)  );
            }
        }
        Thread1 th1 = new Thread1() ;
        th1.start();
        return 0 ;
    }
    private static void ptl(String s) {
        System.out.println( s );
    }
}
